

const common = require('./base/common');

/**
 * 59. 螺旋矩阵 II
 * 
 * @param {number} n
 * @return {number[][]}
 */
var generateMatrix = function (n) {
    if (n <= 0) {
        return [];
    }

    let matrix = [];
    for (let i = 0; i < n; ++i) {
        matrix.push(new Array(n).fill(0));
    }

    let dirs = [[0, 1], [1, 0], [0, -1], [-1, 0]],
        curDir = 0,
        step = 1,
        steps = n * n,
        cur = [0, 0];

    while (step <= steps && matrix[cur[0]][cur[1]] == 0) {
        matrix[cur[0]][cur[1]] = step++;

        let x = cur[0] + dirs[curDir][0],
            y = cur[1] + dirs[curDir][1];
        if (x < 0 || x >= n || y < 0 || y >= n || matrix[x][y]) {
            curDir = (curDir + 1) % dirs.length;
            x = cur[0] + dirs[curDir][0];
            y = cur[1] + dirs[curDir][1];
        }
        cur = [x, y];
    }

    return matrix;
};

/**
 * 54. 螺旋矩阵
 * 
 * @param {number[][]} matrix
 * @return {number[]}
 */
var spiralOrder = function (matrix) {
    let m = matrix.length,
        n = matrix[0].length,
        seen = new Array(m * n).fill(0),
        result = [],
        dirs = [[0, 1], [1, 0], [0, -1], [-1, 0]],
        curDir = 0,
        step = 0,
        cur = [0, 0];

    while (step < seen.length && !seen[cur[0] * n + cur[1]]) {
        result.push(matrix[cur[0]][cur[1]]);
        seen[cur[0] * n + cur[1]] = 1;
        step++;

        let x = cur[0] + dirs[curDir][0],
            y = cur[1] + dirs[curDir][1];
        if (x < 0 || x >= m || y < 0 || y >= n || seen[x * n + y]) {
            curDir = (curDir + 1) % dirs.length;
            x = cur[0] + dirs[curDir][0];
            y = cur[1] + dirs[curDir][1];
        }
        cur = [x, y];
    }

    return result;
};

common.testing([
    generateMatrix(2),
    generateMatrix(3),
    generateMatrix(4),
    generateMatrix(5),
    generateMatrix(6)
])(x => spiralOrder(x));